package com.lkl.hystrixdemo.order.controller;

import com.lkl.hystrixdemo.order.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 *
 * redis分布式锁
 *
 * 如果业务处理时间大于 锁的有效期，则可以添加续命锁，即用守护线程，检测锁的过期时间
 * 当业务没有处理完的时候，则继续添加锁
 */
@RestController
public class DistributedLockController {
    @Autowired
    RedisService redisService;

    private static int num = 0;

    @RequestMapping("/process")
    public String process() {

        String value = UUID.randomUUID().toString().replaceAll("\\-", "");

        boolean isLock = redisService.getLock(value);

        Result result = new Result();

        if (isLock) {
            //开启守护线程 监听当前线程redis锁的变化
            Thread deamo = new DemaonLockThread(redisService, result, value);
            deamo.setDaemon(true);
            deamo.start();

            try {
                Thread.sleep(1000 * 3);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            /*num ++ ;
            System.out.println("执行结果：" + num);*/
            result.isFinished = true;
            //redisService.releaseLock(); 由守护线程释放锁
        } else{
            return "未获取到锁";
        }
        return "SUCCESS";
    }

}


class Result {
    public volatile boolean isFinished = false;
    public Object res;
}
class DemaonLockThread extends Thread{

    private RedisService redisService;

    Result result;

    String value;

    public DemaonLockThread (RedisService redisService, Result result, String value ) {
        this.redisService = redisService;
        this.result = result;
        this.value = value;
    }

    @Override
    public void run() {
        while (!result.isFinished) {
            boolean isLock = redisService.getLock(value);
            System.out.println(Thread.currentThread().getName() + ",是否获取到锁：" + isLock);
            //守护线程获取到锁之后，并且任务没有处理完成，重新设置锁的有效期
            if (!isLock) {
                System.out.println(Thread.currentThread().getName() + ",守护线程一直检验，lock锁还没过期");
                continue;
            }
            System.out.println(Thread.currentThread().getName() + ",守护线程又获取到锁了，但是任务还未完成，继续让任务线程执行");
        }
        redisService.releaseLock(value);
    }
}